#ifndef PLATEMAP_HPP
#define PLATEMAP_HPP

#include "platebaseb.hpp"
#include "analysisresulta.hpp"

class PlateMap
{
public:
    std::vector<PlateBaseB> pmap;
    std::vector<cv::Rect> lastRoi;

public:
    PlateMap()
    {
        pmap.assign(3, PlateBaseB());

        pmap[0].number=10;
        pmap[0].x=0;
        pmap[0].y=0;
        pmap[0].normalAngle=CV_PI;
        pmap[0].vertex[0]=cv::Point2f(-73,0);
        pmap[0].vertex[1]=cv::Point2f(73,0);

        pmap[1].number=67;
        pmap[1].x=0;
        pmap[1].y=3600;
        pmap[1].normalAngle=0;
        pmap[1].vertex[0]=cv::Point2f(-73,0);
        pmap[1].vertex[1]=cv::Point2f(73,0);


        pmap[2].number=89;
        pmap[2].x=2400;
        pmap[2].y=0;
        pmap[2].normalAngle=CV_PI;
        pmap[2].vertex[0]=cv::Point2f(-73,0);
        pmap[2].vertex[1]=cv::Point2f(73,0);

        lastRoi.assign(3, cv::Rect());
    }


    size_t GetActiveIndex()
    {
        size_t i=0;
        for(;i<lastRoi.size();i++)
        {
            if(lastRoi[i].area()>0)
                return i;
        }
        return i;
    }


    void UpdateLocation(cv::Mat &inputImage, const cv::Mat &K, const cv::Mat &D, double angle, AnalysisResult &ar)
    {
        double propertyThres=0.1;

        for(size_t i=0;i<lastRoi.size();i++)
        {
            if(lastRoi[i].area()>0)
            {
                std::cout<<"trace "<<i<<"\n"<<std::flush;

                cv::Scalar hsvThres[2]={
                    //            cv::Scalar(150,-1,150), cv::Scalar(180,256,255)
                    cv::Scalar(-1,-1,110), cv::Scalar(256,256,255)
                    //            cv::Scalar(150,-1,100), cv::Scalar(20,256,255)
                    //            cv::Scalar(140,-1,50), cv::Scalar(40,256,255)
                };

                std::vector<DigitBase> nl;
                cv::Mat bw_label;

                PlateBase::FilterAnalysisCC(inputImage(lastRoi[i]), bw_label, nl, hsvThres);

                std::vector<size_t> numberIndex;

                ar.property=PlateBase::ComputeNumberProperty(nl, numberIndex, pmap[i].number);

                if(ar.property<=0)
                {
                    lastRoi[i]=cv::Rect(0,0,0,0);
                    return;
                }


                for(size_t j=0;j<numberIndex.size();j++)
                {
                    ar.roiDigit[j]=(nl[numberIndex[j]].boundingBox);
                    cv::compare(bw_label(ar.roiDigit[j]), nl[numberIndex[j]].label, ar.bwDigit[j], cv::CMP_EQ);
                    ar.roiDigit[j].x+=lastRoi[i].x;
                    ar.roiDigit[j].y+=lastRoi[i].y;
                }


                cv::Point2f pt2[2];
                pt2[0]=PlateBaseB::RectCenter(ar.roiDigit[0]);
                pt2[1]=PlateBaseB::RectCenter(ar.roiDigit[1]);
                ar.location=pmap[i].Location(pt2[0],0,pt2[1],1,K,D,angle);


                if(ar.property>propertyThres)
                {
                    cv::Size gap;
                    gap.width=gap.height=20+(-ar.location[1]-6000)*(60-20)/(1000-6000);

                    cv::Rect digitSearchRegion[2]={
                        PlateBase::ExpandRoi(ar.roiDigit[0], inputImage.size(), gap),
                        PlateBase::ExpandRoi(ar.roiDigit[1], inputImage.size(), gap)
                    };

                    lastRoi[i]=digitSearchRegion[0]|digitSearchRegion[1];
                }
                else
                {
                    lastRoi[i]=cv::Rect(0,0,0,0);
                }

                return;

            }
        }


        std::cout<<"find new\n"<<std::flush;

        cv::Scalar hsvThres[2]={
            //            cv::Scalar(150,-1,150), cv::Scalar(180,256,255)
            cv::Scalar(-1,-1,110), cv::Scalar(256,256,255)
            //            cv::Scalar(150,-1,100), cv::Scalar(20,256,255)
            //            cv::Scalar(140,-1,50), cv::Scalar(40,256,255)
        };

        std::vector<DigitBase> nl;
        cv::Mat bw_label;

        PlateBase::FilterAnalysisCC(inputImage, bw_label, nl, hsvThres);

        std::vector<double> confidence(lastRoi.size());

        std::vector< std::vector<size_t> > numberIndex(lastRoi.size(), std::vector<size_t>());

        for(size_t i=0;i<lastRoi.size();i++)
            confidence[i]=PlateBase::ComputeNumberProperty(nl, numberIndex[i], pmap[i].number);

        size_t maxIndex=std::max_element(confidence.begin(), confidence.end())-confidence.begin();

        ar.property=confidence[maxIndex];

        if(ar.property<=0)
            return;


        for(size_t i=0;i<numberIndex[maxIndex].size();i++)
        {
            ar.roiDigit[i]=(nl[numberIndex[maxIndex][i]].boundingBox);
            cv::compare(bw_label(ar.roiDigit[i]), nl[numberIndex[maxIndex][i]].label, ar.bwDigit[i], cv::CMP_EQ);
        }


        cv::Point2f pt2[2];
        pt2[0]=PlateBaseB::RectCenter(ar.roiDigit[0]);
        pt2[1]=PlateBaseB::RectCenter(ar.roiDigit[1]);
        ar.location=pmap[maxIndex].Location(pt2[0],0,pt2[1],1,K,D,angle);


        if(ar.property>propertyThres)
        {
            cv::Size gap;
            gap.width=gap.height=20+(-ar.location[1]-6000)*(60-20)/(1000-6000);

            cv::Rect digitSearchRegion[2]={
                PlateBase::ExpandRoi(ar.roiDigit[0], inputImage.size(), gap),
                PlateBase::ExpandRoi(ar.roiDigit[1], inputImage.size(), gap)
            };

            lastRoi[maxIndex]=digitSearchRegion[0]|digitSearchRegion[1];
        }
        else
        {
            lastRoi[maxIndex]=cv::Rect(0,0,0,0);
        }

    }


};


#endif // PLATEMAP_HPP

